package ua.kiev.tosik.price.modules.search.gui;

import org.apache.log4j.Logger;
import org.jdesktop.swingx.JXCollapsiblePane;
import org.jdesktop.swingx.JXPanel;
import ua.kiev.tosik.price.conf.AppConfig;
import ua.kiev.tosik.price.database.DbUtils;
import ua.kiev.tosik.price.database.RowSort;
import ua.kiev.tosik.price.database.dao.IPricesDao;
import ua.kiev.tosik.price.database.factory.AbstractDbFactory;
import ua.kiev.tosik.price.gui.StatusBar;
import ua.kiev.tosik.price.models.Prices;
import ua.kiev.tosik.price.modules.search.PriceSearchModule;
import ua.kiev.tosik.price.modules.search.database.DataQuickFindWorker;

import javax.swing.*;
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Vector;

public class MainPanel implements PropertyChangeListener {

	private static Logger logger = Logger.getLogger("ua.kiev.tosik.price.modules.search.gui");
	private JXPanel panel;
	private PricesTable table;
	private PriceSearchModule module;
	private MainToolBar toolBar;
	private JScrollPane scrollPane;
	private JXCollapsiblePane collapsiblePane;
	private SearchFormPanel searchFormPanel;
	private MainNavigationBar navigationBar;

	private PricesDialog pricesDialog;

	private IPricesDao pricesDao;

	private int resPerPage = 300;

	// private FinderProcess finderProcess;

	public MainPanel() {
		panel = new JXPanel();
		panel.setLayout( new BorderLayout() );

		searchFormPanel = new SearchFormPanel();
		collapsiblePane = new JXCollapsiblePane(JXCollapsiblePane.Direction.RIGHT);
		collapsiblePane.add("Center", searchFormPanel);
		collapsiblePane.setCollapsed(true);

		toolBar = new MainToolBar(this);
		table = new PricesTable(this);
		navigationBar = new MainNavigationBar(this);

		scrollPane = new JScrollPane(table.getTable(), JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);

		panel.add(toolBar.getToolBar(), BorderLayout.NORTH);
		panel.add(scrollPane, BorderLayout.CENTER);
		panel.add(collapsiblePane, BorderLayout.EAST);
		panel.add(navigationBar.getNavBar(), BorderLayout.SOUTH);

		// table.getModel().addTableModelListener(toolBar);

		scrollPane.addMouseWheelListener(new MouseWheelListener() {
			@Override
			public void mouseWheelMoved(MouseWheelEvent e) {
				if ((e.getModifiers() & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK) {
					int row = table.getTable().rowAtPoint(e.getPoint());
					if ( row != -1 ) {
						table.getTable().setEditingRow(table.getTable().rowAtPoint(e.getPoint()));
					}
					if (e.getWheelRotation() > 0) {
						if ((table.getTable().getRowHeight() - 16) >= 16) {
							table.getTable().setRowHeight(table.getTable().getRowHeight() - 16);
						}
					} else {
						table.getTable().setRowHeight(table.getTable().getRowHeight() + 16);
					}
					Rectangle rectangle = table.getTable().getCellRect(row, 0, false);
					if (rectangle != null) {
         			// table.getTable().scrollRectToVisible(rectangle);
						scrollPane.scrollRectToVisible(rectangle);
        			}
				}
			}
		});

		try {
			loadData();
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
	}

	public JXPanel getPanel() {
		return panel;
	}

	public void showSearchPanel(boolean show) {
		collapsiblePane.setCollapsed(!show);
	}

	public PricesTable getTable() {
		return table;
	}

	public PriceSearchModule getModule() {
		return module;
	}

	public void setModule(PriceSearchModule module) {
		this.module = module;
	}

	public MainToolBar getToolBar() {
		return toolBar;
	}

	public IPricesDao getPricesDao() {
		return pricesDao;
	}

	public int getResPerPage() {
		return resPerPage;
	}

	public void viewPrices(int rowIndex) {
		logger.debug("Try to view price record");
		Prices prices = table.getModel().getRow(rowIndex);
		if ( prices == null ) {
			return;
		}
		if ( pricesDialog == null ) {
			pricesDialog = new PricesDialog(this);
		}
		pricesDialog.setPrices(prices);
		pricesDialog.open();
	}

	public void loadData() throws Exception {
		if ( pricesDao == null ) {
			pricesDao = AbstractDbFactory.getInstance(AppConfig.getInstance().get("app.dbtype")).createPricesDao();
		}
		// TODO: Don't create RowSort if it not changed
		if ( table.getCurrentSortColumn() > 0 ) {
			logger.debug("Table sort changed: " + table.getCurrentSortColumn() + " " + table.getCurrentSortType());
			pricesDao.setRowSorter(new RowSort() { {
				setColumn(table.getCurrentSortColumn());
				setType(table.getCurrentSortType());
			}});
		}

		Prices prices = toolBar.getPrices();

		DataQuickFindWorker findWorker = new DataQuickFindWorker(pricesDao, prices);
		findWorker.addPropertyChangeListener(StatusBar.getInstance());
		findWorker.addPropertyChangeListener(this);
		findWorker.execute();
	}

	public void listPrev() {
		if ( ((pricesDao.getOffset()+resPerPage)/resPerPage) == 1 ) { return; }
		pricesDao.setOffset(pricesDao.getOffset()-resPerPage);
		pricesDao.setLimiter(resPerPage);
		try {
			loadData();
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
	}

	public void listNext() {
		if ( pricesDao.getRecordCount() == 0 || DbUtils.countPages(pricesDao.getRecordCount(), resPerPage) == ((pricesDao.getOffset()+resPerPage)/resPerPage) ) {
			return;
		}
		pricesDao.setOffset( pricesDao.getOffset()+resPerPage );
		pricesDao.setLimiter(resPerPage);
		try {
			loadData();
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
	}

	@SuppressWarnings("unused")
	public void destroy() {
		panel = null;
		table = null;
		toolBar = null;
		pricesDialog = null;
		pricesDao = null;
		scrollPane = null;
		searchFormPanel = null;
		collapsiblePane = null;
		navigationBar = null;
	}

	@Override
	@SuppressWarnings("unchecked")
	public void propertyChange(PropertyChangeEvent evt) {
		if ( evt.getPropertyName().equals("SEARCH_START") ) {
			toolBar.setEnable(false);
			navigationBar.enableButton(false);
		}
		if ( evt.getPropertyName().equals("SEARCH_OK") ) {
			navigationBar.enableButton(true);
			toolBar.setEnable(true);
		}
		if ( evt.getPropertyName().equals("PricesList") ) {
			java.util.List<Prices> pricesList = (java.util.List<Prices>)evt.getNewValue();
			if ( toolBar.getPercent() > 0 ) {
				double pr = toolBar.getPercent();
				for ( Prices p: pricesList ) {
					p.setPricePercent( ((pr/100)*p.getPrice())+p.getPrice() );
				}
			}
			getTable().getModel().addRowSet(new Vector<Prices>(pricesList));
			// setRecordFoundInfoText("Fetched " + pricesList.size() + " record(s)");
		}
		if ( evt.getPropertyName().equals("SEARCH_DONE") ) {
			navigationBar.getPageLabel().setText( ((pricesDao.getOffset()+resPerPage)/resPerPage) + " / " + DbUtils.countPages(pricesDao.getRecordCount(), resPerPage) + " (" + pricesDao.getRecordCount() + " total)");
		}
	}

	public void resetDao() {
		pricesDao.setOffset(0);
	}

}
